﻿namespace Nintest.Tests.Graph
{
    using System.Linq;

    using Nintest.Graph;

    using NUnit.Framework;

    [TestFixture]
    public class IncidenceGraphTests
    {
        [Test]
        public void AddVertex()
        {
            var graph = new IncidenceGraph<double, object>();
            var property = new object();

            var v1 = graph.AddVertex(property);
            var v2 = graph.AddVertex(property);

            Assert.That(v1.Property, Is.SameAs(property));
            Assert.That(v2.Property, Is.SameAs(property));
            Assert.That(v1, Is.Not.SameAs(v2));
        }

        [Test]
        [TestCase(new int[0], TestName = "00")]
        [TestCase(new[] { -4 }, TestName = "01")]
        [TestCase(1, 2, 3, 4, TestName = "04")]
        [TestCase(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, TestName = "39")]
        public void Vertices(params int[] expectedProperties)
        {
            var graph = new IncidenceGraph<double, int>();
            foreach (var property in expectedProperties)
                graph.AddVertex(property);

            var vertices = graph.Vertices;
            var actualProperies = vertices.Select(v => v.Property);

            Assert.That(actualProperies, Is.EquivalentTo(expectedProperties));
        }

        [Test]
        public void AddEdge([Values(false, true)] bool sourceMissing, [Values(false, true)] bool targetMissing)
        {
            const int SOURCE_PROPERTY = 1;
            const int TARGET_PROPERTY = 2;
            var graph = new IncidenceGraph<object, int>();
            var source = sourceMissing ? new Vertex<int>(SOURCE_PROPERTY) : graph.AddVertex(SOURCE_PROPERTY);
            var target = targetMissing ? new Vertex<int>(TARGET_PROPERTY) : graph.AddVertex(TARGET_PROPERTY);
            var property = new object();

            var edge = graph.AddEdge(source, target, property);

            Assert.That(edge.Property, Is.SameAs(property));
            Assert.That(edge.Target, Is.SameAs(target));
            Assert.That(graph.Vertices, Contains.Item(source));
            Assert.That(graph.Vertices, Contains.Item(target));
        }

        [Test]
        public void GetOutEdges_ExistingKey()
        {
            var graph = new IncidenceGraph<int, int>();
            var source = graph.AddVertex(1);
            var target = graph.AddVertex(2);
            var edge = graph.AddEdge(source, target, 0);
            var expectedEdges = new[] { edge };

            var outEdges = graph.GetOutEdges(source);

            Assert.That(outEdges, Is.Not.Null);
            Assert.That(outEdges, Is.EquivalentTo(expectedEdges));
        }

        [Test]
        public void GetOutEdges_MissingKey()
        {
            var graph = new IncidenceGraph<int, int>();
            var missingVertex = new Vertex<int>(5);

            var outEdges = graph.GetOutEdges(missingVertex);

            Assert.That(outEdges, Is.Not.Null);
            Assert.That(outEdges, Is.Empty);
            Assert.That(graph.Vertices, Is.Not.Contains(missingVertex));
        }
    }
}